﻿using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace LdCms.Web.Authorizes
{
    using LdCms.Common.Enum;
    using LdCms.Common.Extension;
    using LdCms.Common.Json;
    using LdCms.Common.Time;
    using LdCms.Common.Utility;
    using LdCms.EF.DbEntitiesContext;
    /// <summary>
    /// API接口验证特性类
    /// </summary>
    public class AuthFilterAttribute : ActionFilterAttribute
    {
        private int systemId = BaseSystemConfig.SystemID;
        private bool verify = true;
        /// <summary>
        /// 是否验证
        /// </summary>
        public bool Verify
        {
            get
            {
                return verify;
            }
            set
            {
                verify = value;
            }
        }
        /// <summary>
        /// Action (执行前触发)
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (Verify)
            {
                string message = string.Empty;
                bool verifyResult = IsParams(out message);
                if (!verifyResult)
                {
                    int code = (int)ParamEnum.CommonErrorCode.授权权限不足;
                    object result = new { code, message };
                    context.Result = new ContentResult
                    {
                        Content = result.ToJson(),
                        ContentType = "application/json; charset=utf-8",
                        StatusCode = 200
                    };
                }
            }
            base.OnActionExecuting(context);
        }
        /// <summary>
        /// Action (执行后触发)
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
        }
        /// <summary>
        /// Result (执行前触发)
        /// </summary>
        /// <param name="context"></param>
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            base.OnResultExecuting(context);
        }
        /// <summary>
        /// Result (执行后触发)
        /// </summary>
        /// <param name="context"></param>
        public override void OnResultExecuted(ResultExecutedContext context)
        {
            base.OnResultExecuted(context);
        }

        #region 私有化方法
        private string AppId
        {
            get
            {
                return HttpContext.Current.Request.GetQueryString("appid");
            }
        }
        private string AppSecret
        {
            get
            {
                return HttpContext.Current.Request.GetQueryString("secret");
            }
        }
        private string Uuid
        {
            get
            {
                return HttpContext.Current.Request.GetQueryString("uuid");
            }
        }
        private string Token
        {
            get
            {
                return HttpContext.Current.Request.GetQueryString("token");
            }
        }
        private string AccessToken
        {
            get
            {
                return HttpContext.Current.Request.GetQueryString("access_token");
            }
        }
        private bool IsParams(out string errMsg)
        {
            try
            {
                bool result = true;
                errMsg = "ok";
                string queryString = HttpContext.Current.Request.GetHttpWebQueryString();
                var sParams = Utility.UrlParamsToDictionary(queryString);
                foreach (var item in sParams)
                {
                    string name = item.Key.ToLower().Trim();
                    string value = item.Value.ToLower().Trim();
                    switch (name)
                    {
                        case "appid":
                            result = IsAppId(out errMsg);
                            break;
                        case "uuid":
                            result = IsUuid(out errMsg);
                            break;
                        case "token":
                            result = IsToken(out errMsg);
                            break;
                        case "access_token":
                            result = IsAccessToken(out errMsg);
                            break;
                    }
                    if (!result)
                    {
                        return result;
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private bool IsAppId(out string errMsg)
        {
            try
            {
                string appId = AppId;
                string appSecret = AppSecret;
                if (appId.Length != (int)ParamEnum.TokenType.AppID)
                {
                    errMsg = "appid error";
                    return false;
                }
                using (var db = new LdCmsDbEntitiesContext())
                {
                    int errCode = -1;
                    var result = db.SP_Verify_Sys_InterfaceAccountByAppID(systemId, appId, appSecret, out errCode, out errMsg);
                    return errCode == 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private bool IsUuid(out string errMsg)
        {
            try
            {
                string uuid = Uuid;
                if (uuid.Length != (int)ParamEnum.TokenType.Uuid)
                {
                    errMsg = "uuid error";
                    return false;
                }
                errMsg = "";
                return true;
                //TODO:
                using (var db = new LdCmsDbEntitiesContext())
                {
                    int errCode = -1;
                    var result = db.SP_Verify_Sys_InterfaceAccountByUuid(systemId, uuid, out errCode, out errMsg);
                    return errCode == 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private bool IsToken(out string errMsg)
        {
            try
            {
                string token = Token;
                if (token.Length != (int)ParamEnum.TokenType.Token)
                {
                    errMsg = "token error";
                    return false;
                }
                using (var db = new LdCmsDbEntitiesContext())
                {
                    int timestamp = TimeHelper.GetUnixTimestampTen();
                    int errCode = -1;
                    var result = db.SP_Verify_Sys_InterfaceAccessToken(token, timestamp, out errCode, out errMsg);
                    return errCode == 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private bool IsAccessToken(out string errMsg)
        {
            try
            {
                string accessToken = AccessToken;
                int accessTokenLength = accessToken.Length;
                int[] arrAccessToken = new int[] { (int)ParamEnum.TokenType.Member, (int)ParamEnum.TokenType.Staff };
                if (!arrAccessToken.Contains(accessTokenLength))
                {
                    errMsg = "access_token error";
                    return false;
                }
                using (var db = new LdCmsDbEntitiesContext())
                {
                    int timestamp = TimeHelper.GetUnixTimestampTen();
                    int errCode = -1;
                    if (accessTokenLength == (int)ParamEnum.TokenType.Member)
                    {
                        var result = db.SP_Verify_Member_AccessToken(accessToken, timestamp, out errCode, out errMsg);
                    }
                    else
                    {
                        var result = db.SP_Verify_Institution_StaffAccessToken(accessToken, timestamp, out errCode, out errMsg);
                    }
                    return errCode == 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

    }

}
